﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using BusinessBingo.Common.Interfaces;
using BusinessBingo.Data.DataLoadOptions;
using BusinessBingo.Data.DataOrderOptions;
using BusinessBingo.Data.Filter;
using BusinessBingo.Data.Interfaces;
using BusinessBingo.Model;

namespace BusinessBingo.Data
{
    public class EFGameRepository : EFBaseRepository, IGameRepository
    {
        public EFGameRepository(IUnitOfWork unitOfWork, IGuid portalGuid)
            : base(unitOfWork, portalGuid)
        {
        }

        public IList<Model.Game> GetItems(GameDataLoadOptions dlo, GameDataOrderOptions doo, GameFilter filter)
        {
            ObjectQuery<Game> query = this.GetQuery(dlo, doo, filter);
            IList<Game> items = query.ToList();

            IList<Model.Game> result = new List<Model.Game>();

            foreach (Game item in items)
            {
                result.Add(Mapping.MapGame(item));
            }

            return result;
        }
        
        public int GetItemsCount(GameFilter filter)
        {
            ObjectQuery<Game> query = this.GetQuery(null, null, filter);
            return query.Count();
        }

        public Model.Game AddItem(Model.Game item)
        {
            item.Id = this._portalGuid.New;

            Game g = new Game();
            g.Id = item.Id;
            g.Number = item.Number;
            g.GroupId = item.GroupId;

            this._context.Games.AddObject(g);

            return item;
        }

        public ObjectQuery<Data.Game> GetQuery(GameDataLoadOptions dlo, GameDataOrderOptions doo, GameFilter filter)
        {
            ObjectQuery<Game> query = this._context.Games;

            return query.LoadWith(dlo).FilterFor(filter).OrderBy(doo);
        }
    }

    internal static class GameQueryExtensions
    {
        public static ObjectQuery<Game> FilterFor(this ObjectQuery<Game> query, GameFilter filter)
        {
            if (filter == null) return query;

            if (filter.WithId.HasValue == true)
                query = (ObjectQuery<Game>)query.Where(x => x.Id.Equals(filter.WithId.Value));

            if (filter.WithGroupId.HasValue == true)
                query = (ObjectQuery<Game>)query.Where(x => x.GroupId.Equals(filter.WithGroupId.Value));

            if (filter.WithGameNumber.HasValue == true)
                query = (ObjectQuery<Game>)query.Where(x => x.Number.Equals(filter.WithGameNumber.Value));

            if (filter.OnlyLastGame == true)
                query = (ObjectQuery<Game>) query.OrderByDescending(x => x.Number).Take(1);


            return query;
        }

        public static ObjectQuery<Game> LoadWith(this ObjectQuery<Game> query, GameDataLoadOptions dlo)
        {
            GameDataLoadOptions sdlo = (GameDataLoadOptions)dlo;

            if (sdlo == null) return query;

            return query;
        }

        public static ObjectQuery<Game> OrderBy(this ObjectQuery<Game> query, GameDataOrderOptions doo)
        {
            return query;
        }
    }
}